//{==================================================================================================
//! @file NPrimaryNumber.cpp
//! @date 2013-09-29
//! @mainpage Programm for finding prime integer number N
//! @author Kirill Shcherbatov <kshcherbatov@gmail.com>, 376 group, DCAM MIPT
//! @version 1.0
//! @note Task C, varriant 2, test 2007, MIPT
//}===================================================================================================

//****************************************************************************************************
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//****************************************************************************************************

//****************************************************************************************************
#define _EJC
#define PARANOIC_MODE
//****************************************************************************************************

//****************************************************************************************************
//! @def   OUT
//! @note  -Use OUT to print your text in console. It is checking _EJC declaration.
//! @note  -Only if _EJC is defined then the program prints your text.
//! @note  --You also can define _EJC in compilation command (g++ main.cpp -D _EJC)
//----------------------------------------------------------------------------------------------------
#ifdef _EJC
    #define OUT printf
#else
    #define OUT if (0) printf
#endif // _EJC
//****************************************************************************************************


//****************************************************************************************************
//! @def    VALID
//! @param  CONDITIONAL for checking
//! @param  MESSAGE for displaying if CONDITIONAL is false
//! @note   -It checks the validity of the expression.
//! @note   -Program will use OUT to display MESSAGE
//! @note   -If sended conditional is false, program will be terminated sending 1 message
//----------------------------------------------------------------------------------------------------
#ifdef  PARANOIC_MODE
    #define VALID( CONDITIONAL, MESSAGE )       \
    if (!(CONDITIONAL))                         \
    {                                           \
        OUT  ( MESSAGE );                       \
        exit ( 1 );                             \
    } // VALID in PARANOIC_MODE
#else
    #define VALID ( CONDITIONAL, MESSAGE ) \
    CONDITIONAL;
#endif
//****************************************************************************************************

//****************************************************************************************************
//! @def    CHECK
//! @param  CONDITIONAL for checking
//! @param  MESSAGE for displaying if CONDITIONAL is false
//! @note   -It checks the validity of the expression.
//! @note   -Program will use OUT to display MESSAGE
//! @note   -If sended conditional is false, program will be terminated sending 1 message
//! @warning   IN RELIASE MODE IT WILL BE REMOOVED
//----------------------------------------------------------------------------------------------------
#ifdef PARANOIC_MODE
    #define CHECK( CONDITIONAL, MESSAGE )       \
    if (! (CONDITIONAL))                         \
    {                                           \
        OUT  ( MESSAGE );                       \
        exit ( 1 );                            \
    } // CHECK in PARANOIC_MODE
#else
    #define CHECK ( CONDITIONAL, MESSAGE )
#endif
//****************************************************************************************************

//****************************************************************************************************
long long unsigned int find_prime_number_N ( short unsigned int N );
int IsPrime (long long unsigned int p);
//****************************************************************************************************


//****************************************************************************************************
//! @param - number of sending arguments
//! @param argv[] - arguments, include generated by OS
//! @return 0 on success
//----------------------------------------------------------------------------------------------------
int main (int, const char* argv[])
{
    OUT ( "%s (%s) %s %s:\n\n", argv[ 0 ], __FILE__, __DATE__, __TIME__ );
    OUT ( "#Programm for finding prime int. number N N&(0; 10 000]\n" );

    const unsigned short int SUPRENUM = 10000;

    OUT ( "#Enter your's number N\n"
          "#N = ");

    unsigned short int N = 0;

    VALID ( scanf ("%llu",&N) == 1 , "#Problems with inputed N. Read the instructions above & try again.\n" );

    CHECK ( N > 0 ,  "#Inputed N is incorrect. N should be greater than 0.\n" );
    CHECK ( N < SUPRENUM , "#Inputed N is incorrect. N should be lower than 10 000.\n");
    long long unsigned int result = find_prime_number_N (N);
    VALID (result != 0, "#Sorry, it looks like bug in a programm code in function find_prime_number_N (),"
                        "please report the developer..\n")

    OUT ("#Ok, the prime integer number %u is ",N);
    printf ("%llu\n",result);
    return 0;
}
//****************************************************************************************************

//****************************************************************************************************
//! @param N number of prime integer to find
//! @return prime number on succes
//----------------------------------------------------------------------------------------------------
long long unsigned int find_prime_number_N ( short unsigned int N )
{
    long long unsigned int cure_N = 1;
    short unsigned int already_finded = 0;
    while (already_finded++ < N)
    {
        while (!IsPrime (cure_N++));
    }
    return cure_N-1;
}
//****************************************************************************************************


//****************************************************************************************************
//! @param p - integer for primary-checking
//! @return 1 if p is prime, else 0
//----------------------------------------------------------------------------------------------------
int IsPrime (long long unsigned int p)
{
    if (p == 1) return 0;
    if (p == 2) return 1;
    for (register long long unsigned int i = 2; i < sqrt (p)+1; i++ )
        if (p % i == 0) return 0;
    return 1;
}
//****************************************************************************************************
